/**
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 * $Id$ PersistenceServicesMock.java
 * Universidad de los Andes (Bogotá - Colombia)
 * Departamento de Ingeniería de Sistemas y Computación
 * Licenciado bajo el esquema Academic Free License version 2.1
 *
 * Ejercicio: Muebles los Alpes
 * Autor: Camilo Alvarez
 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 */
package com.losalpes.catalogo.servicios;

import com.losalpes.catalogo.entities.Mueble;
import com.losalpes.catalogo.entities.RegistroVenta;
import com.losalpes.catalogo.entities.Usuario;
import com.losalpes.catalogo.entities.Vendedor;
import com.losalpes.catalogo.excepciones.InvalidOperationException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Random;
import javax.annotation.security.DeclareRoles;
import javax.annotation.security.RolesAllowed;
import javax.ejb.Stateless;

/**
 * Implementación de los servicios de persistencia que se le prestan al sistema.
 * @author Camilo Alvarez
 */
@Stateless
@DeclareRoles({"Administrador", "Gerente"})
public class PersistenceServicesMock implements IPersistenceServices,IPersistenceServicesRemote {

    // -----------------------------------------------
    // Atributos
    // -----------------------------------------------
    /**
     * Objeto que almacena los datos en memoria principal. [Implementación temporal]
     */
    private static ArrayList<Vendedor> sDataVendedores;
    /**
     * Objeto que almacena los datos en memoria principal. [Implementación temporal]
     */
    private static ArrayList<Mueble> sDataMuebles;
    /**
     * Objeto que almacena los datos en memoria principal. [Implementación temporal]
     */
    private static ArrayList<Usuario> sDataUsuarios;

    private static ArrayList<RegistroVenta> sDataRegistrosVentas;

    // -----------------------------------------------
    // Constructor
    // -----------------------------------------------
    /**
     * Constructor de la clase. Inicializa los atributos.
     */
    public PersistenceServicesMock() {
        if (sDataVendedores == null) {
            sDataVendedores = new ArrayList();
            for (int i = 0; i < 20; i++) {
                Vendedor vendedor = new Vendedor();
                vendedor.setIdentificacion(i + "");
                vendedor.setNombres("Nombre " + i);
                vendedor.setApellidos("Apellidos " + i);
                vendedor.setSalario(1500);
                sDataVendedores.add(vendedor);
            }
            sDataMuebles = new ArrayList();
            for (int i = 0; i < 10; i++) {
                Mueble mueble = new Mueble();
                mueble.setReferencia(i + "");
                mueble.setNombre("Mueble " + i);
                mueble.setDescripcion("Descrip " + i);
                mueble.setCantidad(i);
                sDataMuebles.add(mueble);
            }
            sDataUsuarios=new ArrayList();
            Usuario user = new Usuario();
            user.setUsuario("CLIENTE");
            user.setDocumento("15753");
            user.setNombreCompleto("Germán Sotelo");
            user.setPwd("123");
            sDataUsuarios.add(user);
            sDataRegistrosVentas = new ArrayList<RegistroVenta>();
            Random r = new Random();
            for(int e=0;e<10;e++){
                RegistroVenta venta = new RegistroVenta();
                venta.setCantidad(e);
                venta.setProducto(sDataMuebles.get(e));
                venta.setFechaVenta(new Date(r.nextInt()));
                venta.setCiudad("Bogota");
            }
        }

    }

    // -----------------------------------------------
    // Métodos
    // -----------------------------------------------
    /**
     * Permite crear un objeto dentro de la persistencia del sistema.
     * @param obj. Objeto que representa la instancia de la entidad que se quiere crear.
     */
    @RolesAllowed("Administrador")
    public void create(Object obj)throws InvalidOperationException{
        if (obj instanceof Vendedor) {
            Vendedor v = (Vendedor) obj;
            v.setIdentificacion(sDataVendedores.size() + "");
            sDataVendedores.add(v);
        } else if (obj instanceof Mueble) {
            Mueble m = (Mueble) obj;
            m.setReferencia(sDataMuebles.size() + "");
            sDataMuebles.add(m);
        }
        else if (obj instanceof Usuario){
            Usuario m = (Usuario) obj;
            for(Usuario us:sDataUsuarios){
                if(us.getUsuario().equals(m.getUsuario()))throw new InvalidOperationException("El usuario '"+m.getUsuario()+"' ya ha sido registrado en el sistema");
                if(us.getDocumento().equals(m.getDocumento()))throw new InvalidOperationException("El usuario con documento '"+m.getDocumento()+"' ya ha sido registrado en el sistema");
            }
            sDataUsuarios.add(m);
        }
        else if (obj instanceof RegistroVenta) {
            sDataRegistrosVentas.add((RegistroVenta)obj);
        }
    }

    /**
     * Permite modificar un objeto dentro de la persistencia del sistema.
     * @param obj. Objeto que representa la instancia de la entidad que se quiere modificar.
     */
    @RolesAllowed("Administrador")
    public void update(Object obj) {
        if (obj instanceof Vendedor) {
            sDataVendedores.set(sDataVendedores.indexOf(obj), (Vendedor) obj);
        } else if (obj instanceof Mueble) {
            sDataMuebles.set(sDataMuebles.indexOf(obj), (Mueble) obj);
        }else if (obj instanceof Usuario) {
            sDataUsuarios.set(sDataUsuarios.indexOf(obj), (Usuario) obj);
        }
    }

    /**
     * Permite borrar un objeto dentro de la persistencia del sistema.
     * @param obj. Objeto que representa la instancia de la entidad que se quiere borrar.
     */
    @RolesAllowed("Administrador")
    public void delete(Object obj)throws InvalidOperationException{
        if (obj instanceof Vendedor) {
            Vendedor vendedorABorrar = (Vendedor) obj;
            if (vendedorABorrar != null && vendedorABorrar.getIdentificacion() != null) {
                for (int e = 0; e < sDataVendedores.size(); e++) {
                    Vendedor ven = (Vendedor) sDataVendedores.get(e);
                    if (ven.getIdentificacion().equals(vendedorABorrar.getIdentificacion())) {
                        sDataVendedores.remove(e);
                        break;
                    }
                }
            }
        } else if (obj instanceof Mueble) {
            Mueble muebleABorrar = (Mueble) obj;
            if (muebleABorrar != null && muebleABorrar.getReferencia() != null) {
                for (int e = 0; e < sDataMuebles.size(); e++) {
                    Mueble ven = (Mueble) sDataMuebles.get(e);
                    if (ven.getReferencia().equals(muebleABorrar.getReferencia())) {
                        sDataMuebles.remove(e);
                        break;
                    }
                }
            }
        }
        else if (obj instanceof Usuario){
            Usuario usuarioABorrar = (Usuario) obj;
            for(RegistroVenta rv : sDataRegistrosVentas){
                if(rv.getComprador().getUsuario().equals(usuarioABorrar.getUsuario())){
                    System.out.print("no borrado");
                    throw new InvalidOperationException("El usuario ha realizado comprar y por lo tanto no puede ser eliminado del sistema.");
                }
            }
            if (usuarioABorrar != null && usuarioABorrar.getUsuario() != null) {
                for (int e = 0; e < sDataUsuarios.size(); e++) {
                    Usuario ven = (Usuario) sDataUsuarios.get(e);
                    if (ven.getUsuario().equals(usuarioABorrar.getUsuario())) {
                        sDataUsuarios.remove(e);
                        System.out.print("borrado");
                        break;
                    }
                }
            }
        }
        //System.out.println(obj.getClass());
    }

    /**
     * Retorna la lista de todos los elementos de una clase dada que se encuentran en el sistema.
     * @param c. Clase cuyos objetos quieren encontrarse en el sistema.
     * @return list. Listado de todos los objetos de una clase dada que se encuentran en el sistema.
     */
    @RolesAllowed("Administrador")
    public List findAll(Class c) {
        if (c.equals(Mueble.class)) {
            return sDataMuebles;
        } else if (c.equals(Vendedor.class)) {
            return sDataVendedores;
        } else if (c.equals(Usuario.class)) {
            return sDataUsuarios;
        } else if (c.equals(RegistroVenta.class)) {
            return sDataRegistrosVentas;
        }else {
            return null;
        }

    }

    /**
     * Retorna la instancia de una entidad dado un identificador y la clase de la entidadi.
     * @param c. Clase de la instancia que se quiere buscar.
     * @param id. Identificador unico del objeto.
     * @return obj. Resultado de la consulta.
     */
    @RolesAllowed("Administrador")
    public Object findById(Class c, Object id) {
        if (c.equals(Vendedor.class)) {
            for (Object v : findAll(c)) {
                Vendedor ven = (Vendedor) v;
                if (ven.getIdentificacion().equals(id)) {
                    return ven;
                }
            }
        } else if (c.equals(Mueble.class)) {
            for (Object v : findAll(c)) {
                Mueble mue = (Mueble) v;
                if (mue.getReferencia().equals(id)) {
                    return mue;
                }
            }
        }
        else if (c.equals(Usuario.class)) {
            for (Object v : findAll(c)) {
                Usuario mue = (Usuario) v;
                if (mue.getUsuario().equals(id)) {
                    return mue;
                }
            }
        }
        return null;
    }
}